﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Phoenix.ReflectionExtensions;
using PServiceBus.Core.Runtime.Extensions;
using System.Collections;
using System.Text.RegularExpressions;
using PServiceBus.Core.Runtime.Transports;
using PServiceBus.Core.Provider;

namespace PServiceBus.Core.Runtime.Messages {
    public sealed class MessageMapperToken {
        private object _message;
        private bool _excludeXmlItemsAttribute;
        private static Regex _itemRegex = new Regex(@"<Items type=""Items"">(?<Xml>(.*?))</Items>", RegexOptions.Multiline | RegexOptions.IgnoreCase);
        internal MessageMapperToken(object message, bool excludeXmlItemsAttribute) {
            _message = message;
            _excludeXmlItemsAttribute = excludeXmlItemsAttribute;
        }

        private static string GetMessageProperty(object message, string name, bool excludeXmlItemsAttribute) {
            var value = string.Empty;
            MethodHelper.Try(() =>
            {
                var properties = name.Split('.');
                var obj = message;
                foreach (var propertyName in properties) {
                    var objType = obj.GetType();
                    obj = objType.GetPropertyEx(propertyName).GetValueEx(obj);
                }
                value = obj.IsValidForXml() ? obj.ToXml().InnerXml() : obj.ToString();
                value = obj is IList && excludeXmlItemsAttribute ? value.InnerXml() : value;

                if (excludeXmlItemsAttribute)
                    while (_itemRegex.IsMatch(value))
                        value = _itemRegex.Replace(value, "$1");
            });
            return value;
        }

        public string ToString(TransportFormat format) {
            var transformation = TransportProvider.GetTransformation(format);
            return transformation.Transform(_message.ToDict());
        }

        public string this[string propertyName] {
            get { return GetMessageProperty(_message, propertyName, _excludeXmlItemsAttribute); }
        }
    }
}
